socket = require "socket"

host = "www.w3.org"

--[[单独
    local c = assert(socket.connect(host, 80))
    c:send("GET " .. "/TR/2018/SPSD-html32-20180315/" .. " HTTP/1.0\r\n\r\n")
    while true do
        local s, status, partial = c:receive(2^10)
        io.write(s or partial)
        if status == "closed" then break end
    end
    c:close()
--]]

----[[多个
    lfs = {
        "/TR/REC-html32.html",
        "/TR/2018/SPSD-html32-20180315/",
        "/TR/1999/REC-html401-19991224/html40.txt",
        "/TR/2002/REC-xhtml1-20200801/xhtml1.pdf",
        "/TR/2000/REC-DOM-Level-2-Core-20001113/DOM2-Core.txt",
    }

    local receive

    local function download(host, file)
        local c = assert(socket.connect(host, 80))
        local cnt = 0
        c:send("GET " .. file .. " HTTP/1.0\r\n\r\n")
        c:settimeout(0)
        while true do
            local s, status, partial = receive(c)
            if status == "timeout" then
                coroutine.yield(c)
            end
            cnt = cnt + #(s or partial)
            if #(s or partial) ~= 0 then
                print(file .. ":" .. cnt)
            end
            if status == "closed" then break end
        end
        c:close()
        print(file, cnt)
    end

    function receive(connection)
        connection:settimeout(0)
        local s, status, partial = connection:receive(1024)
        if status == "timeout" then
            coroutine.yield(connection)
        end
        return s or partial, status
    end

    local threads = {}
    local connections = {}

    local function get(host, file)
        local co = coroutine.create(function()
            download(host, file)
        end)
        table.insert(threads, co)
    end

    local function dispatch()
        local i = 1
        while true do
            if threads[i] == nil then
                if threads[1] == nil then break end
                i = 1
                connections = {}
            end
            local status, res = coroutine.resume(threads[i])
            if not res then
                table.remove(threads, i)
            else
                i = i + 1
                table.insert(connections, res)
                if #connections == #threads then
                    socket.select(connections)
                end
            end
        end
    end

    get(host, lfs[1])
    get(host, lfs[2])
    get(host, lfs[3])
    get(host, lfs[4])
    get(host, lfs[5])

    dispatch()
--]]